<?php

/**
 * 静态工具类
 */
class Tools {

    /**
     * 获取全球唯一标识
     * @return type
     */
    public static function getUniId() {
        return sprintf(
                '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
        );
    }

    /**
     * encode数据
     * @param array $data
     * @return string
     */
    public static function encode($data) {
        foreach ($data as $k => & $v) {
            if (is_array($v))
                $v = implode('|', $v);
        }
        unset($v);
        return implode(',', $data);
    }

    /**
     * decode数据
     * @param string $data
     * @return array
     */
    public static function decode($data) {
        if ($data == '')
            return array();
        $arr = explode(',', $data);
        foreach ($arr as $k => & $v) {
            if (stripos($v, '|') !== FALSE)
                $v = explode('|', $v);
        }
        unset($v);
        return $arr;
    }

    /**
     * 取URL段值
     * @param int $index 索引位置
     * @param mixed $default 默认值
     * @param string $slash 是否添加/,first/final 前后添加
     * @return mixed
     */
    public static function segment($index, $default = '', $slash = '') {
        $index = $index <= 0 ? 0 : $index;
        $url = array_slice(explode('/', self::getCurrentURL()), 1);
        if (isset($url[$index]) && $url[$index] != '') {
            if ($slash == 'first' || $slash == 'forward' || $slash == 'before') {
                return '/' . $url[$index];
            } else if ($slash == 'final' || $slash == 'behind' || $slash == 'after') {
                return $url[$index] . '/';
            } else {
                return $url[$index];
            }
        } else {
            return $default;
        }
    }

    /**
     * 将所传参数打印到页面上
     */
    public static function p() {
        $arg_list = func_get_args();
        $arg_nums = func_num_args();
        $temp = array();
        for ($i = 0; $i < $arg_nums; $i++) {
            $temp[] = print_r($arg_list[$i], true);
        }
        echo '<pre style="text-align: left;color:blue;">';
        echo implode(" :)\n", $temp);
        echo '</pre>';
    }

    /**
     * 将所传参数写入日志
     */
    public static function d() {
        $arg_list = func_get_args();
        $arg_nums = func_num_args();
        $temp = array();
        for ($i = 0; $i < $arg_nums; $i++) {
            $temp[] = print_r($arg_list[$i], true);
        }
        Logger::getInstance()->log(implode(" :)\n", $temp), 'log');
    }

    public static function baseurl($full = false) {
        static $baseurl = null;
        if (is_null($baseurl)) {
            if ($baseurl == '') {
                $url = trim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])), '/');
                $url = !$url ? '' : "/{$url}";
                $baseurl = $url;
            }
            $returnurl = $baseurl;
        } else {
            $returnurl = $baseurl;
        }
        if ($full) {
            $domain = isset($_SERVER['HTTP_HOST']) && stripos($_SERVER['HTTP_HOST'], ':') !== false ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
            $returnurl = 'http://' . $domain . $baseurl;
        }
        $module = strtolower(Yaf_Dispatcher::getInstance()->getRequest()->getModuleName());
        $returnurl = rtrim($returnurl, '/') . (Yaf_Application::app()->getConfig('yaf')->get('subdomain') ? '' : '/' . $module . '/');
        $returnurl = !$returnurl ? '/' : $returnurl;
        return $returnurl;
    }

    public static function siteurl($url = '', $full = false) {
        if (is_array($url))
            $url = implode('/', $url);
        $hassuffix = substr($url, -1, 1) === '/';
        $baseurl = self::baseurl($full);
        $url = trim($url, '/');
        $baseurl = rtrim(rtrim($baseurl, '/') . '/' . $url, '/');
        return $baseurl .= ($hassuffix ? '/' : '');
    }

    public static function success($msg, $url = '-1', $time = 2000) {
        self::showMessage($msg, $url, $time, 'success');
    }

    public static function error($msg, $url = '-1', $time = 2000) {
        self::showMessage($msg, $url, $time, 'error');
    }

    public static function info($msg, $url = '-1', $time = 2000) {
        self::showMessage($msg, $url, $time, 'info');
    }

    public static function alert($msg, $url = '-1') {
        if ((string) $url == '-1') {
            $url = "history.go(-1);";
        } else {
            $url = "location.href='{$url}';";
        }
        echo "<script>alert('{$msg}');{$url}</script>";
    }

    /**
     * 中文字符截取
     * @param string $string 截取的字符数据
     * @param int $length 截取的字符长度
     * @param string $dot 截取后的字符加上的字符，默认为...
     * @param string $charset 字符编码，默认为utf-8
     * @return string 截取后的数据
     */
    public static function cutstr($string, $length, $dot = '...', $charset = 'utf-8') {
        if (strlen($string) <= $length || $length <= 0)
            return $string;
        $string = str_replace(array('&nbsp;', '&amp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;'), array(' ', '&', '"', "'", '“', '”', '—', '<', '>', '·', '…'), $string);
        $strcut = '';
        if (strtolower($charset) == 'utf-8') {
            $n = $tn = $noc = 0;
            while ($n < strlen($string)) {
                $t = ord($string[$n]);
                if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
                    $tn = 1;
                    $n++;
                    $noc++;
                } else if (194 <= $t && $t <= 223) {
                    $tn = 2;
                    $n += 2;
                    $noc += 2;
                } else if (224 <= $t && $t < 239) {
                    $tn = 3;
                    $n += 3;
                    $noc += 2;
                } else if (240 <= $t && $t <= 247) {
                    $tn = 4;
                    $n += 4;
                    $noc += 2;
                } else if (248 <= $t && $t <= 251) {
                    $tn = 5;
                    $n += 5;
                    $noc += 2;
                } else if ($t == 252 || $t == 253) {
                    $tn = 6;
                    $n += 6;
                    $noc += 2;
                } else {
                    $n++;
                }
                if ($noc >= $length)
                    break;
            }
            if ($noc > $length)
                $n -= $tn;
            $strcut = substr($string, 0, $n);
        } else {
            for ($i = 0; $i < $length - strlen($dot) - 1; $i++)
                $strcut .= ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i];
        }
        $strcut = str_replace(array('&', '"', '<', '>'), array('&', '"', '&lt;', '&gt;'), $strcut);
        return $strcut . $dot;
    }

    /**
     * 提示消息
     * @param string $message 消息内容
     * @param string $url 跳转到的地址 -1为后退
     * @param int $time 跳转等待时间，单位为毫秒
     * @param string $type 类型 success/error/help/fav/alert alert为弹出窗口(此时$time无效)
     */
    public static function showMessage($message, $url = '-1', $time = 3000, $type = 'success') {
        //$time = ($time == 0) ? 3000 : $time;
        if ($url == '')
            $url = '-1';
        if ((string) $url == '-1')
            $url = "javascript:history.go(-1);";
        if ($type == 'alert') {
            echo "<script type='text/javascript'>alert(\"" . str_replace("\"", "“", $message) . "\");location.href='{$url}'</script>";
        } else {
            $site = Yaf_Registry::get("config")->site->toArray();
            $image = "/assets/images/tips/" . $type . ".gif";
            $title = "温馨提示";
            $time = ceil($time / 1000);
            $script = '';
            $script .= "<script type='text/javascript'>
                    function jump_url(){
                    remain = parseInt(document.getElementById('timeid').innerHTML);
                    if(remain > 1){
                        document.getElementById('timeid').innerHTML = remain-1;
                        setTimeout('jump_url()', 1000);
                    }else{
                        location.href = \"{$url}\";
                    }
               }";
            $script .= ( $url != 'javascript:;' && $url != '') ? "setTimeout('jump_url()', 1000);" : "";
            $script .= '</script>';

            include APPLICATION_PATH . '/views/error/showmessage.phtml';
        }
        exit;
    }

    /**
     * 读取时区偏移秒数
     * @return int
     */
    public static function getTimezoneOffset($name) {
        $timezone = new DateTimeZone($name);
        return $timezone->getOffset(new DateTime("now", $timezone));
    }

    /**
     * 二维数组排序(保留索引,但只能排序一个字段)
     * @param array $arr 需要排序的数组
     * @param string $field 排序字段 默认为weigh
     * @param string $sort 排序方式 SORT_ASC或SORT_DESC
     * @return array
     */
    public static function getArraySortIndex($arr, $field = 'weigh', $sort = "SORT_ASC") {
        $ret = $sorter = array();
        foreach ($arr as $k => $v) {
            $sorter[$k] = $v[$field];
        }

        natcasesort($sorter);
        foreach ($sorter as $k => $v) {
            $ret[$k] = $arr[$k];
        }

        if (strtoupper($sort) == "SORT_DESC") {
            $ret = array_reverse($ret, true);
        }
        return $ret;
    }

    /**
     * 二维数组排序(数字索引数组将重建索引)
     * @param array $arr 需要排序的数组 二维数组
     * @param string $arg1 排序的键名或字段名
     * @param string $arg2 排序的顺序 SORT_ASC或SORT_DESC
     * @param string $arg3 排序的方法 SORT_REGULAR
     * @return array
     */
    public static function getArraySort($arr, $arg1, $arg2 = "SORT_ASC", $arg3 = "SORT_REGULAR") {
        if (!is_array($arr) || !$arr) {
            return $arr;
        }
        $argcount = func_num_args();
        for ($i = 1; $i < $argcount; $i++) {
            $arg = func_get_arg($i);
            if (!preg_match("/SORT_(.*)/i", $arg)) {
                $keynamelist[] = $arg;
                $sortrule[] = '$' . $arg;
            } else {
                $sortrule[] = $arg;
            }
        }
        foreach ($arr AS $key => $info) {
            foreach ($keynamelist AS $keyname) {
                ${$keyname}[$key] = $info[$keyname];
            }
        }
        $evalstring = 'array_multisort(' . join(",", $sortrule) . ',$arr);';
        eval($evalstring);
        return $arr;
    }

    /**
     * 一维数组相加
     * @return array
     */
    public static function getArrayPlus() {
        $c = array();
        $argv = func_get_args();
        foreach ($argv as $m => $n) {
            foreach ($n as $k => $v) {
                if (isset($c[$k])) {
                    $c[$k] = $c[$k] + $n[$k];
                } else {
                    $c[$k] = $n[$k];
                }
            }
        }
        return $c;
    }

    /**
     * 一维数组相加
     * @return array
     */
    public static function arrayAdd() {
        $c = array();
        $argv = func_get_args();
        foreach ($argv as $m => $n) {
            foreach ($n as $k => $v) {
                if (isset($c[$k])) {
                    $c[$k] = $c[$k] + $n[$k];
                } else {
                    $c[$k] = $n[$k];
                }
            }
        }
        return $c;
    }

    public static function arrayMergeMulti() {
        // Holds all the arrays passed
        $params = func_get_args();

        // First array is used as the base, everything else overwrites on it
        $return = array_shift($params);

        // Merge all arrays on the first array
        foreach ($params as $array) {
            foreach ($array as $key => $value) {
                // Numeric keyed values are added (unless already there)
                if (is_numeric($key)) {
                    if (is_array($value)) {
                        $return [] = self::arrayMergeMulti($return [$$key], $value);
                    } else {
                        $return [] = $value;
                    }
                    // String keyed values are replaced
                } else {
                    if (isset($return [$key]) && is_array($value) && is_array($return [$key])) {
                        $return [$key] = self::arrayMergeMulti($return [$key], $value);
                    } else {
                        $return [$key] = $value;
                    }
                }
            }
        }

        return $return;
    }

    /**
     * array_map多维数组版
     * @param string $callback
     * @param array $array
     * @return array
     */
    public static function arrayMapRecursive($callback, $array) {
        foreach ($array as $key => $value) {
            if (is_array($array[$key])) {
                $array[$key] = self::arrayMapRecursive($callback, $array[$key]);
            } else {
                $array[$key] = call_user_func($callback, $array[$key]);
            }
        }
        return $array;
    }

    /**
     * 判断IP是否在黑名单里
     * @param string $userip 用户IP
     * @param array $badiplist 禁止访问的IP及IP段数组
     * @return boolean
     */
    public static function checkIPForbidden($userip, $badiplist) {
        //$badip = explode("\n",$badiplist);
        $badip = $badiplist;
        $ippart = explode(".", $userip);
        if (!is_array($badip))
            return false;
        for ($i = 0; $i < count($badip); $i++) {
            $m = 0;
            $badippart = explode(".", $badip[$i]);
            for ($j = 0; $j < count($badippart); $j++) {
                if ((trim((string) $badippart[$j]) == "*") || (trim((string) $ippart[$j]) == trim((string) $badippart[$j]))) {
                    $m++;
                }
            }
            if ($m == 4)
                return true;
        }
        return false;
    }

    /**
     * 判断传入的字符是否含有非法字符
     * @param string $string 判断的数据
     * @return boolean 有非法字符返回true,无返回字符返回false
     */
    public static function checkFilterWord($string = '') {
        $words = file_get_contents(BASE_PATH . '/tmp/text/denywords.txt');
        $words = array_filter(explode("\r\n", $words));
        $words = str_replace($words, '**', $string);
        return stripos($words, "**") !== false ? true : false;
    }

    /**
     * 获取过滤后的字符数据
     * @param string $string 过滤的数据
     * @param string $filter 替换的字符,默认为***
     * @return string
     */
    public static function getFilterWord($string = '', $filter = '***') {
        $words = file_get_contents(BASE_PATH . '/tmp/text/denywords.txt');
        $words = array_filter(explode("\r\n", $words));
        return str_replace($words, $filter, $string);
    }

    /**
     * 格式化文件大小
     * @param int $size 大小值，以B为单位
     * @return string
     */
    public static function formatBytes($size) {
        $sizename = array('Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
        return $size ? round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $sizename[$i] : '0 Bytes';
    }

    /**
     * 格式化时间为相对人类时间
     * @param int $date UNIX时间格式的值
     * @param bool $showdate 当未获取到指定人类时间时，是否显示普通时间，默认为true
     * @return string 处理后的人类时间
     */
    public static function formatTime($date, $showdate = true) {
        if (!is_numeric($date))
            return date("Y-m-d");
        $limit = time() - $date;
        if ($limit < 0)
            return '来自古代';
        else if ($limit == 0)
            return '刚刚';
        else if ($limit < 60)
            return $limit . '秒钟前';
        else if ($limit >= 60 && $limit < 3600)
            return floor($limit / 60) . '分钟前';
        else if ($limit >= 3600 && $limit < 86400)
            return floor($limit / 3600) . '小时前';
        else if ($limit >= 86400 && $limit < 604800)
            return floor($limit / 86400) . '天前';
        else if ($limit >= 604800 && $limit < 2592000)
            return floor($limit / 604800) . '周前';
        else if ($limit >= 2592000 && $limit < 31536000)
            return floor($limit / 2592000) . '个月前';
        else if ($limit >= 31536000 && $limit < 315360000)
            return floor($limit / 31536000) . '年前';
        else
            return ($limit >= 315360000 && $showdate) ? date('Y-m-d H:i:s', $date) : '';
    }

    /**
     * 获取客户端IP
     * @return string 获取的IP地址
     */
    public static function getRemoteAddr() {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] &&
                (!isset($_SERVER['REMOTE_ADDR']) || preg_match('/^127\..*/i', trim($_SERVER['REMOTE_ADDR'])) ||
                preg_match('/^172\.16.*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^192\.168\.*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^10\..*/i', trim($_SERVER['REMOTE_ADDR'])))) {
            if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',')) {
                $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                return $ips[0];
            } else {
                return $_SERVER['HTTP_X_FORWARDED_FOR'];
            }
        }
        return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1';
    }

    /**
     * 获取unixtime转换后的时间值
     * @param mixed $unixtime 数组或unixtime
     * @param bool $showtime 是否显示时间
     * @param bool $longtime 是否为13位时间
     * @return mixed 
     */
    public static function getDateTime($unixtime = 0, $showtime = true, $longtime = false) {
        $is_array = is_array($unixtime);
        $unixtime = $is_array ? $unixtime : array($unixtime);
        foreach ($unixtime as $m => $n) {
            //$n = $n ? $n : time();
            $unixtime[$m] = date(($showtime ? 'Y-m-d H:i:s' : 'Y-m-d'), ($longtime ? $n / 1000 : $n));
        }
        return $is_array ? $unixtime : $unixtime[0];
    }

    /**
     * 获取当前脚本的URL地址
     * @return string
     */
    public static function getCurrentURL() {
        if (php_sapi_name() == 'cli') {
            return isset($_SERVER['argv'][1]) ? str_replace('request_uri=', '', $_SERVER['argv'][1]) : '/';
        } else {
            if (!empty($_SERVER["REQUEST_URI"])) {
                $script_name = $_SERVER["REQUEST_URI"];
                $nowurl = $script_name;
            } else {
                $script_name = $_SERVER["PHP_SELF"];
                $nowurl = empty($_SERVER["QUERY_STRING"]) ? $script_name : $script_name . "?" . $_SERVER["QUERY_STRING"];
            }
        }
        return $nowurl;
    }

    /**
     * 获取文件后缀
     * @param string $str 文件名
     * @return string
     */
    public static function getExtension($str) {
        return strtolower(substr(strrchr($str, '.'), 1));
    }

    /**
     * 写入配置文件
     * @param array $config 配置信息
     * @param string $prefix 配置前缀
     * @param string $filename 存储的文件名
     * @return array
     */
    public static function writeIniFile($config, $prefix, $filename = '') {
        $a = array();
        if (isset($config['_comment'])) {
            $a[] = ';' . $config['_comment'];
            unset($config['_comment']);
        }
        foreach ($config as $k => $v) {
            $c = $prefix ? array($prefix) : $prefix;
            $c[] = $k;
            $c = array(implode('.', $c));
            if (is_array($v)) {
                $a[] = self::writeIniFile($v, implode('.', $c));
                continue;
            } else {
                $c[] = is_bool($v) ? ($v ? 1 : 0) : ( is_string($v) ? '"' . $v . '"' : $v);
            }
            $a[] = implode('=', $c);
        }
        $data = implode("\r\n", $a);
        //如果传递了文件路径则将配置写入文件
        if ($filename) {
            file_put_contents($filename, $data);
        }
        return $data;
    }

    /**
     * 移除XSS
     * @param $str
     * @return mixed
     */
    public static function removeXSS($str) {
        $str = str_replace('<!--  -->', '', $str);
        $str = preg_replace('~/\*[ ]+\*/~i', '', $str);
        $str = preg_replace('/\\\0{0,4}4[0-9a-f]/is', '', $str);
        $str = preg_replace('/\\\0{0,4}5[0-9a]/is', '', $str);
        $str = preg_replace('/\\\0{0,4}6[0-9a-f]/is', '', $str);
        $str = preg_replace('/\\\0{0,4}7[0-9a]/is', '', $str);
        $str = preg_replace('/&#x0{0,8}[0-9a-f]{2};/is', '', $str);
        $str = preg_replace('/&#0{0,8}[0-9]{2,3};/is', '', $str);
        $str = preg_replace('/&#0{0,8}[0-9]{2,3};/is', '', $str);

        $str = htmlspecialchars($str);
        //$str = preg_replace('/&lt;/i', '<', $str);
        //$str = preg_replace('/&gt;/i', '>', $str);
        // 非成对标签
        $lone_tag = array("img", "param", "br", "hr");
        foreach ($lone_tag as $key => $val) {
            $val = preg_quote($val);
            $str = preg_replace('/&lt;' . $val . '(.*)(\/?)&gt;/isU', '<' . $val . "\\1\\2>", $str);
            $str = self::transCase($str);
            $str = preg_replace_callback('/<' . $val . '(.+?)>/i', create_function('$temp', 'return str_replace("&quot;","\"",$temp[0]);'), $str);
        }
        $str = preg_replace('/&amp;/i', '&', $str);

        // 成对标签
        $double_tag = array("table", "tr", "td", "font", "a", "object", "embed", "p", "strong", "em", "u", "ol", "ul", "li", "div", "tbody", "span", "blockquote", "pre", "b", "font");
        foreach ($double_tag as $key => $val) {
            $val = preg_quote($val);
            $str = preg_replace('/&lt;' . $val . '(.*)&gt;/isU', '<' . $val . "\\1>", $str);
            $str = self::transCase($str);
            $str = preg_replace_callback('/<' . $val . '(.+?)>/i', create_function('$temp', 'return str_replace("&quot;","\"",$temp[0]);'), $str);
            $str = preg_replace('/&lt;\/' . $val . '&gt;/is', '</' . $val . ">", $str);
        }
        // 清理js
        $tag = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'behaviour', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base', 'font');

        foreach ($tag as $tag) {
            $tag = preg_quote($tag);
            $str = preg_replace('/' . $tag . '\(.*\)/isU', '\\1', $str);
            $str = preg_replace('/' . $tag . '\s*:/isU', $tag . '\:', $str);
        }
        $str = preg_replace('/[\s]+on[\w]+[\s]*=/is', '', $str);
        return $str;
    }

    public static function transcase($str) {
        $str = preg_replace('/(e|ｅ|Ｅ)(x|ｘ|Ｘ)(p|ｐ|Ｐ)(r|ｒ|Ｒ)(e|ｅ|Ｅ)(s|ｓ|Ｓ)(s|ｓ|Ｓ)(i|ｉ|Ｉ)(o|ｏ|Ｏ)(n|ｎ|Ｎ)/is', 'expression', $str);
        return $str;
    }

    /**
     * 判断Unix时间是否9满足Cron指定的条件
     * @param string $time 时间
     * @param string $cron Cron标准格式
     * @return boolean
     */
    public static function isTimeCron($time, $cron) {
        $cron_parts = explode(' ', $cron);
        if (count($cron_parts) != 5) {
            return false;
        }
        list($min, $hour, $day, $mon, $week) = explode(' ', $cron);
        $to_check = array('min' => 'i', 'hour' => 'G', 'day' => 'j', 'mon' => 'n', 'week' => 'w');
        $ranges = array(
            'min' => '0-59',
            'hour' => '0-23',
            'day' => '1-31',
            'mon' => '1-12',
            'week' => '0-6',
        );

        foreach ($to_check as $part => $c) {
            $val = $$part;
            $values = array();
            if (strpos($val, '/') !== false) {
                //Get the range and step
                list($range, $steps) = explode('/', $val);
                //Now get the start and stop
                if ($range == '*') {
                    $range = $ranges[$part];
                }
                list($start, $stop) = explode('-', $range);
                for ($i = $start; $i <= $stop; $i = $i + $steps) {
                    $values[] = $i;
                }
            } else {
                $k = explode(',', $val);
                foreach ($k as $v) {
                    if (strpos($v, '-') !== false) {
                        list($start, $stop) = explode('-', $v);

                        for ($i = $start; $i <= $stop; $i++) {
                            $values[] = $i;
                        }
                    } else {
                        $values[] = $v;
                    }
                }
            }
            if (!in_array(date($c, $time), $values) and ( strval($val) != '*')) {
                return false;
            }
        }
        return true;
    }

    /**
     * 生成随机字符
     * @param int $length 随机字符长度
     * @param string $prefix 固定字符前缀
     * @return string
     */
    public static function getRandNum($length = 10, $prefix = '') {
        $list = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        mt_srand((double) microtime() * 1000000);
        if ($length > 0) {
            while (strlen($prefix) < ($length)) {
                $prefix .= $list[mt_rand(0, strlen($list) - 1)];
            }
        }
        return (string) $prefix;
    }

    /**
     * 获取文本中的远程图片地址
     * @param string $str 文本内容
     * @return array
     */
    public static function getImages($str) {
        preg_match_all('/<img(.+)src=[\'\"]?([^\'\"]+)[\'\"]?/i', stripslashes($str), $matches, PREG_PATTERN_ORDER);
        $result = array();
        $images = $matches[2];
        foreach ($images as $value) {
            if (in_array(self::getExtension($value), array('gif', 'jpg', 'jpeg', 'png')))
                $result[] = $value;
        }
        return $result;
    }

    /**
     * 获取远程图片并下载
     * @param string $url 远程URL
     * @param string $dst_dir 本地存放目录
     * @param string $dst_filename 本地文件名，不带扩展名
     * @return string
     */
    public static function getRemoteImage($url, $dst_dir, $dst_filename = false) {
        if (!empty($url)) {
            if (!$dst_filename) {
                $fileurl = uniqid() . strrchr($url, ".");
            } else {
                $fileurl = $dst_filename . strrchr($url, ".");
            }
            $filepath = BASE_PATH . $dst_dir;
            $filename = $filepath . $fileurl;
            if (!is_dir($filepath))
                self::mkdirs($filepath);
            $get_file = @file_get_contents($url);
            if ($get_file) {
                $fp = @fopen($filename, "w");
                @fwrite($fp, $get_file);
                @fclose($fp);
                return $dst_dir . $fileurl;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * 获得在线GOOGLE的翻译结果
     * @param string $text 翻译的文字
     * @param string $from 源语言，默认为zh-CN，可选zh-CN(中文),en(英文)
     * @param string $to 目标语言，默认为en，可选zh-CN(中文),en(英文)
     * @param string $replacespace 替换空格，默认为空格
     * @return string 翻译成功后的结果
     */
    public static function getGoogleTranslate($text, $from = 'zh-CN', $to = 'en', $replacespace = '-') {
        $text = preg_replace(array('/(\?|&|\/)/i'), '', $text);
        if (empty($text))
            return '';
        $content = @file_get_contents("http://translate.google.cn/translate_t?sl={$from}&tl={$to}&text=" . urlencode($text) . "#");
        if (!$content || empty($content))
            return false;
        preg_match_all("/<span\sid=result_box\sclass=\"short_text\">(.*?)<\/span>/si", $content, $matchs);
        return str_replace(' ', $replacespace, strip_tags(iconv("GB2312", "UTF-8", trim($matchs[0][0]))));
    }

    /**
     * HTML转文本简化,只替换style,frame,script,br
     * @param string $str 需要替换的字符
     * @return string
     */
    public static function getCleanText($str) {
        $from = array("�", "�", "�", "®", "Ʒ", "ԋ", "ტ", "“", "”", "‘", "’", "?", "Ż݄", "€", "Ψ", "†", "‚", "ƒ", '"', '…', '‡', 'ˆ', '‰', "Š", '‹', 'Œ', 'Ž', "'", "'", '"', '"', '•', '–', '—', '˜', '™', 'š', '›', 'œ', 'ž', 'Ÿ', '¡', '¢', '£', '¤', '¥', '¦', '§', '¨', '©', 'ª', '«', '¬', '®', '¯', '°', '±', '²', '³', '´', 'µ', '¶', '·', '¸', '¹', 'º', '»', '¼', '½', '¾', '¿', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', "ÿ");
        $str = str_replace($from, '', $str);
        $str = preg_replace("/<sty(.*)\\/style>|<scr(.*)\\/script>|<scr(.*)\\/script>|<!--(.*)-->/isU", '', $str);
        return strip_tags(str_replace(array('<br />', '<br>', '<br/>'), "\n", $str));
    }

    /**
     * 替换文本中的远程图片地址
     * @param string $str 文本内容
     * @param bool $water_mark 是否添加水印，默认为false
     * @return string
     */
    public static function getReplacedImageContent($str) {
        $imgs = self::getImages($str);
        if (!is_array($imgs))
            return $str;
        $localimg = array();
        foreach ($imgs as $img) {
            if (substr($img, 0, 7) == 'http://') {
                $file = file_get_contents($img);
                if ($file) {
                    $ext = self::getExtension($img);
                    $filename = uniqid() . '.' . $ext;
                    $dst_dir = '/assets/item/' . date("Ymd") . "/";
                    self::mkdirs(BASE_PATH . $dst_dir);
                    $name_path = BASE_PATH . $dst_dir . $filename;
                    $fp = fopen($name_path, 'a');
                    @fwrite($fp, $file);
                    @fclose($fp);
                    $img = $dst_dir . $filename;
                }
            }
            $localimg[] = $img;
        }
        return str_replace($imgs, $localimg, $str);
    }

    /**
     * CURL发送Request请求,含POST和REQUEST
     * @param string $url 请求的链接
     * @param mixed $params 传递的参数
     * @param string $method 请求的方法
     * @param mixed $options CURL的参数
     * @return array
     */
    public static function sendRequest($url, $params = array(), $method = 'POST', $options = array()) {
        $method = strtoupper($method);
        $protocol = substr($url, 0, 5);
        $query_string = is_array($params) ? http_build_query($params) : $params;

        $ch = curl_init();
        $defaults = array();
        if ('GET' == $method) {
            $geturl = $query_string ? $url . (stripos($url, "?") !== false ? "&" : "?") . $query_string : $url;
            $defaults[CURLOPT_URL] = $geturl;
        } else {
            $defaults[CURLOPT_URL] = $url;
            $defaults[CURLOPT_POST] = 1;
            $defaults[CURLOPT_POSTFIELDS] = $query_string;
        }

        $defaults[CURLOPT_HEADER] = false;
        $defaults[CURLOPT_USERAGENT] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.98 Safari/537.36";
        $defaults[CURLOPT_FOLLOWLOCATION] = true;
        $defaults[CURLOPT_RETURNTRANSFER] = true;
        $defaults[CURLOPT_CONNECTTIMEOUT] = 3;
        $defaults[CURLOPT_TIMEOUT] = 3;

        // disable 100-continue
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));

        if ('https' == $protocol) {
            $defaults[CURLOPT_SSL_VERIFYPEER] = false;
            $defaults[CURLOPT_SSL_VERIFYHOST] = false;
        }

        curl_setopt_array($ch, (array) $options + $defaults);

        $ret = curl_exec($ch);
        $err = curl_error($ch);

        if (false === $ret || !empty($err)) {
            $errno = curl_errno($ch);
            $info = curl_getinfo($ch);
            curl_close($ch);
            return array(
                'result' => false,
                'errno' => $errno,
                'msg' => $err,
                'info' => $info,
            );
        }
        curl_close($ch);
        return array(
            'result' => true,
            'msg' => $ret,
        );
    }

    /**
     * 异步发送一个请求
     * @param string $url 请求的链接
     * @param mixed $params 请求的参数
     * @param string $method 请求的方法
     * @return boolean TRUE
     */
    public static function sendAsyncRequest($url, $params = array(), $method = 'POST') {
        $method = strtoupper($method);
        $method = $method == 'POST' ? 'POST' : 'GET';
        //构造传递的参数
        if (is_array($params)) {
            $post_params = array();
            foreach ($params as $k => &$v) {
                if (is_array($v))
                    $v = implode(',', $v);
                $post_params[] = $k . '=' . urlencode($v);
            }
            $post_string = implode('&', $post_params);
        }else {
            $post_string = $params;
        }
        $parts = parse_url($url);
        //构造查询的参数
        if ($method == 'GET' && $post_string) {
            $parts['query'] = isset($parts['query']) ? $parts['query'] . '&' . $post_string : $post_string;
            $post_string = '';
        }
        $parts['query'] = isset($parts['query']) && $parts['query'] ? '?' . $parts['query'] : '';
        //发送socket请求,获得连接句柄
        $fp = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 3);
        if (!$fp)
            return FALSE;
        //设置超时时间
        stream_set_timeout($fp, 3);
        $out = "{$method} {$parts['path']}{$parts['query']} HTTP/1.1\r\n";
        $out.= "Host: {$parts['host']}\r\n";
        $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
        $out.= "Content-Length: " . strlen($post_string) . "\r\n";
        $out.= "Connection: Close\r\n\r\n";
        if ($post_string !== '')
            $out .= $post_string;
        fwrite($fp, $out);
        //不用关心服务器返回结果
        //echo fread($fp, 1024);
        fclose($fp);
        return TRUE;
    }

    /**
     * 获得数组元素的概率
     * @param array $ps array('p1'=>20, 'p2'=>30, 'p3'=>50);
     * @param array $num 默认为1,即随机出来的数量
     * @param array $unique 默认为true,即当num>1时,随机出的数量是否唯一
     * @return mixed 当num为1时返回键名,反之返回一维数组
     */
    public static function random($ps, $num = 1, $unique = true) {
        if (!$ps) {
            return $num == 1 ? '' : array();
        }
        if ($num >= count($ps) && $unique) {
            $res = array_keys($ps);
            return $num == 1 ? $res[0] : $res;
        }
        $max_exp = 0;
        $res = array();
        foreach ($ps as $key => $value) {
            $value = substr($value, 0, stripos($value, ".") + 6);
            $exp = strlen(strchr($value, '.')) - 1;
            if ($exp > $max_exp) {
                $max_exp = $exp;
            }
        }
        $pow_exp = pow(10, $max_exp);
        if ($pow_exp > 1) {
            reset($ps);
            foreach ($ps as $key => $value) {
                $ps[$key] = $value * $pow_exp;
            }
        }
        $pro_sum = array_sum($ps);
        if ($pro_sum < 1) {
            return $num == 1 ? '' : array();
        }
        for ($i = 0; $i < $num; $i++) {
            $rand_num = mt_rand(1, $pro_sum);
            reset($ps);
            foreach ($ps as $key => $value) {
                if ($rand_num <= $value) {
                    break;
                } else {
                    $rand_num -= $value;
                }
            }
            if ($num == 1) {
                $res = $key;
                break;
            } else {
                $res[$i] = $key;
            }
            if ($unique) {
                $pro_sum -= $value;
                unset($ps[$key]);
            }
        }
        return $res;
    }

    /**
     * 语言方法
     */
    public static function translate() {
        return "";
        if (!Yaf_Registry::get('config')->lang) {
            Load::getInstance()->config('lang', 'lang', BASE_PATH . '/conf/' . Yaf_Registry::get('config')->game->languages->api . '.ini');
        }
        $args = func_get_args();
        $value = Yaf_Registry::get('config')->lang->{"$args[0]"};
        if (!$value || !isset($args[1]))
            return $value ? : $args[0];
        $args[0] = $value;
        return call_user_func_array('sprintf', $args);
    }

    /**
     * 获取一个基于时间的Unix时间戳
     * @param string $type 时间类型，默认为day，可选minute,hour,day,week,month,quarter,year
     * @param int $offset 时间偏移量 默认为0，正数表示当前type之后，负数表示当前type之前
     * @param string $position 时间的开始或结束，默认为begin，可选前(begin,start,first,front)，end
     * @param int $year 基准年，默认为null，即以当前年为基准
     * @param int $month 基准月，默认为null，即以当前月为基准
     * @param int $day 基准天，默认为null，即以当前天为基准
     * @param int $hour 基准小时，默认为null，即以当前年小时基准
     * @param int $minute 基准分钟，默认为null，即以当前分钟为基准
     * @return int 处理后的Unix时间戳
     */
    public static function getUnixTime($type = 'day', $offset = 0, $position = 'begin', $year = null, $month = null, $day = null, $hour = null, $minute = null) {
        $year = is_null($year) ? date('Y') : $year;
        $month = is_null($month) ? date('m') : $month;
        $day = is_null($day) ? date('d') : $day;
        $hour = is_null($hour) ? date('H') : $hour;
        $minute = is_null($minute) ? date('i') : $minute;
        $position = in_array($position, array('begin', 'start', 'first', 'front'));

        switch ($type) {
            case 'minute':
                return $position ? mktime($hour, $minute + $offset, 0, $month, $day, $year) : mktime($hour, $minute + $offset, 59, $month, $day, $year);
                break;
            case 'hour':
                return $position ? mktime($hour + $offset, 0, 0, $month, $day, $year) : mktime($hour + $offset, 59, 59, $month, $day, $year);
                break;
            case 'day':
                return $position ? mktime(0, 0, 0, $month, $day + $offset, $year) : mktime(23, 59, 59, $month, $day + $offset, $year);
                break;
            case 'week':
                return $position ?
                        mktime(0, 0, 0, $month, $day - date("w", mktime(0, 0, 0, $month, $day, $year)) + 1 - 7 * (-$offset), $year) :
                        mktime(23, 59, 59, $month, $day - date("w", mktime(0, 0, 0, $month, $day, $year)) + 7 - 7 * (-$offset), $year);
                break;
            case 'month':
                return $position ? mktime(0, 0, 0, $month + $offset, 1, $year) : mktime(23, 59, 59, $month + $offset, get_month_days($month + $offset, $year), $year);
                break;
            case 'quarter':
                return $position ?
                        mktime(0, 0, 0, 1 + ((ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) - 1) * 3, 1, $year) :
                        mktime(23, 59, 59, (ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) * 3, get_month_days((ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) * 3, $year), $year);
                break;
            case 'year':
                return $position ? mktime(0, 0, 0, 1, 1, $year + $offset) : mktime(23, 59, 59, 12, 31, $year + $offset);
                break;
            default:
                return mktime($hour, $minute, 0, $month, $day, $year);
                break;
        }
    }

    public static function sendToBrowser($file, $delaftersend = true, $exitaftersend = true) {
        if (file_exists($file) && is_readable($file)) {
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment;filename = ' . basename($file));
            header('Content-Transfer-Encoding: binary');
            header('Expires: 0');
            header('Cache-Control: must-revalidate, post-check = 0, pre-check = 0');
            header('Pragma: public');
            header('Content-Length: ' . filesize($file));
            ob_clean();
            flush();
            readfile($file);
            if ($delaftersend) {
                unlink($file);
            }
            if ($exitaftersend) {
                exit;
            }
        }
    }

    /**
     * 从数组构造成INI格式数据
     * @param array $config
     * @param string$prefix
     * @return sring
     */
    public static function getIniFromArray($config = array(), $prefix = 'game') {
        $lastconf = array();
        if (is_array($config)) {
            //注释
            if (isset($config['_comment'])) {
                $lastconf[] = ';' . $config['_comment'];
                unset($config['_comment']);
            }
            //配置内容
            foreach ($config as $k => $v) {
                if (is_array($v)) {
                    $lastconf[] = self::getIniFromArray($v, $prefix . "." . $k);
                } else {
                    $quote = is_numeric($v) || is_bool($v) || $v == 'true' || $v == 'false' ? '' : '"';
                    $lastconf[] = $prefix . "." . $k . "=" . $quote . $v . $quote;
                }
            }
        }
        return implode("\r\n", $lastconf);
    }

    /**
     * 递归创建目录
     */
    public static function mkdirs($dir) {
        if (empty($dir))
            return false;
        if (!is_dir($dir)) {
            self::mkdirs(dirname($dir));
            mkdir($dir);
        }
    }

    /**
     * 上传文件并同步到又拍云
     * @param string $string
     * @param string $path
     * @return boolean
     */
    public static function savefile($string, $path) {
        if ($string && $path) {
            Tools::mkdirs(dirname(BASE_PATH . $path));
            if (is_file($string)) {
                move_uploaded_file($string, BASE_PATH . $path);
            } else {
                $img = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $string));
                file_put_contents(BASE_PATH . $path, $img);
            }
            $db = Yaf_Registry::get("db");
            $one = $db->one("SELECT * FROM {pre}upload WHERE url = ?", array($path));
            if (!$one) {
                $values = array(
                    'url' => $path,
                    'filesize' => filesize(BASE_PATH . $path),
                    'createtime' => time()
                );
                $db->insert("{pre}upload", $values);
            }
            /*
              $upyun = Upyun::getInstance();
              try {
              $upyun->upload($path);
              return TRUE;
              } catch (Exception $e) {
              return FALSE;
              }
             * 
             */
            //异步发送到又拍云
            Tools::sendAsyncRequest(Yaf_Registry::get('config')->site->nodejsurl, array('id' => 0, 'url' => '', 'image' => $path, 'action' => 'upload'), 'GET');
        } else {
            return FALSE;
        }
    }

    /**
     * 删除文件并删除又拍云数据
     * @param string $path
     * @return boolean
     */
    public static function deletefile($path) {
        Yaf_Registry::get("db")->query("DELETE FROM {pre}upload WHERE url = ?", array($path));
        if (file_exists(BASE_PATH . $path)) {
            @unlink(BASE_PATH . $path);
        }
        $upyun = Upyun::getInstance();
        try {
            $upyun->delete($path);
            return TRUE;
        } catch (Exception $e) {
            return FALSE;
        }
    }

}
